﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AXImServer
{
    /// <summary>
    /// 内存业务逻辑
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="PK"></typeparam>
    public class MemoryBusiness<T, PK> : IBusiness<T, PK>
        where T : class
        where PK : class
    {
        private IList<T> data_list = new List<T>();

        public Func<PK> NextPK { get; set; }
        public Func<PK, T> GetItemByPK { get; set; }
        public Func<T, PK> GetItemPK { get; set; }
        public Action<T, PK> SetItemPK { get; set; }
        public Func<IOrderBy, T, T, int> CompareItem { get; set; }
        public Func<IFilter, T, bool> FilterItem { get; set; }

        public bool Add(T t)
        {
            if (NextPK != null && SetItemPK != null)
            {
                var pk = NextPK();
                SetItemPK(t, pk);
            }

            data_list.Add(t);
            return true;
        }

        public int Remove(T t)
        {
            return data_list.Remove(t) ? 1 : 0;
        }

        public int RemoveByFilter(IFilter filter)
        {
            int count = 0;

            if (FilterItem != null)
            {
                for (int i = data_list.Count - 1; i >= 0; --i)
                {
                    var item = data_list[i];
                    if (FilterItem(filter, item))
                    {
                        data_list.RemoveAt(i);
                        ++count;
                    }
                }
            }

            return count;
        }

        public int RemoveByPK(PK pk)
        {
            int count = 0;
            if (GetItemByPK != null)
            {
                var item = GetItemByPK(pk);
                if (item != null)
                {
                    data_list.Remove(item);
                    count++;
                }
            }
            return count;
        }

        public bool Update(T t)
        {
            bool success = false;

            if (GetItemPK != null)
            {
                PK pk = GetItemPK(t);
                foreach (var item in data_list)
                {
                    PK item_pk = GetItemPK(item);

                    if (pk.Equals(item_pk))
                    {
                        foreach (var field in t.GetType().GetFields())
                        {
                            var value = field.GetValue(t);
                            field.SetValue(item, value);
                        }

                        success = true;
                        break;
                    }
                }
            }

            return success;
        }

        public T Get(PK pk)
        {
            if (GetItemByPK != null)
                return GetItemByPK(pk);

            return default(T);
        }

        public T GetFirstByFilter(IFilter filter, IOrderBy orderby = null)
        {
            List<T> t_list = new List<T>();
            t_list.AddRange(data_list);

            if (CompareItem != null && orderby != null)
                t_list.Sort((a, b) => CompareItem(orderby, a, b));

            T item = default(T);

            if (FilterItem != null)
            {
                foreach (var d_item in data_list)
                {
                    if (FilterItem(filter, d_item))
                    {
                        item = d_item;
                        break;
                    }
                }
            }

            return item;
        }

        public IEnumerable<T> GetList(IEnumerable<PK> pks)
        {
            List<T> list = new List<T>();

            if (GetItemByPK != null)
            {
                foreach (var pk in pks)
                {
                    var item = GetItemByPK(pk);
                    if (item != null)
                        list.Add(item);
                }
            }

            return list;
        }

        public IEnumerable<T> GetAll(IOrderBy orderby = null)
        {
            List<T> t_list = new List<T>();
            t_list.AddRange(data_list);

            if (CompareItem != null && orderby != null)
                t_list.Sort((a, b) => CompareItem(orderby, a, b));

            return t_list;
        }

        public IEnumerable<T> GetAllByFilter(IFilter filter, IOrderBy orderby = null)
        {
            List<T> t_list = new List<T>();
            List<T> n_list = new List<T>();
            t_list.AddRange(data_list);

            if (CompareItem != null && orderby != null)
                t_list.Sort((a, b) => CompareItem(orderby, a, b));

            if (FilterItem != null)
            {
                foreach (var d_item in data_list)
                {
                    if (FilterItem(filter, d_item))
                    {
                        n_list.Add(d_item);
                    }
                }
            }

            return n_list;
        }
    }
}
